home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / msoftapp.zip / BOUNCE.CPP < prev    next >
C/C++ Source or Header  |  1993-06-01  |  7KB  |  271 lines

  1. // bounce.cpp : Defines the class behaviors for the Bounce child window.
  2.  
  3. #include"viewer.h"
  4.  
  5. BEGIN_MESSAGE_MAP(CBounceWin, CMDIChildWnd)
  6.     ON_WM_CREATE()
  7.     ON_WM_DESTROY()
  8.     ON_WM_SIZE()
  9.     ON_WM_TIMER()
  10.     ON_WM_MDIACTIVATE()
  11.     ON_COMMAND(IDM_BLACK, OnColor)
  12.     ON_COMMAND(IDM_RED,   OnColor)
  13.     ON_COMMAND(IDM_GREEN, OnColor)
  14.     ON_COMMAND(IDM_BLUE,  OnColor)
  15.     ON_COMMAND(IDM_WHITE, OnColor)
  16.     ON_COMMAND(IDM_CUSTOM, OnColor)
  17.     ON_COMMAND(IDM_SLOW,  OnSpeed)
  18.     ON_COMMAND(IDM_FAST,  OnSpeed)
  19. END_MESSAGE_MAP()
  20.  
  21. // COULD BE REPLACED WITH TEMPLATE
  22. #define ABS(x) ((x) < 0? -(x) : (x) > 0? (x) : 0)
  23.  
  24. // Create: register custom WndClass and create a window.
  25. // This must be done because CBounceWin has a custom cursor.
  26. BOOL CBounceWin::Create(LPCSTR szTitle, DWORD style, const RECT& rect,
  27.     CMDIFrameWnd* parent)
  28.     {
  29.     const char* pszBounceClass = // register a custom Window class
  30.         AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW,
  31.             LoadCursor(NULL, IDC_UPARROW), 
  32.             (HBRUSH)(COLOR_WINDOW+1),
  33.             NULL);
  34.  
  35.     return CMDIChildWnd::Create(pszBounceClass, szTitle, style, rect, parent);
  36.     }
  37.  
  38. CBounceWin::CBounceWin(void)
  39.     {
  40.     m_pBitmap = NULL;
  41.     m_pMenuCurrent = NULL;
  42.     m_bWindowActive = FALSE;
  43.     m_nColor = IDM_BLACK;
  44.     m_clrBall = clrTextArray[m_nColor - IDM_BLACK];
  45.     }
  46.  
  47. CBounceWin::~CBounceWin(void)
  48.     {
  49.         // Suppress Foundation DestroyMenu done in CMenu destructor 
  50.         // (Windows takes care of menu cleanup for the active window)
  51.     if(m_bWindowActive)
  52.         m_pMenuCurrent->Detach();
  53.     delete m_pBitmap;
  54.     if(m_nSpeed != 0)
  55.         KillTimer(1);
  56.     }
  57.  
  58.  
  59. // OnCreate: Set up the ball parameters and start a timer.
  60. int CBounceWin::OnCreate(LPCREATESTRUCT)
  61.     {
  62.     m_nSpeed = IDM_SLOW;
  63.     if(!SetTimer(1,(m_nSpeed == IDM_SLOW ? 100 : 0), NULL))
  64.         {
  65.         MessageBox("Not enough timers available for this window.",
  66.                 "Viewer | Bounce", MB_ICONEXCLAMATION | MB_OK);
  67.         m_nSpeed = 0;
  68.         return -1;        // signal creation failure...
  69.         }
  70.     else
  71.         {
  72.         CDC* pDC = GetDC();
  73.         m_xPixel = pDC->GetDeviceCaps(ASPECTX);
  74.         m_yPixel = pDC->GetDeviceCaps(ASPECTY);
  75.         ReleaseDC(pDC);
  76.  
  77.     // Note that we could call MakeNewBall here (which should be called
  78.     // whenever the ball's speed, color or size has been changed), but the
  79.     // OnSize member function is always called after the OnCreate. Since
  80.     // the OnSize member has to call MakeNewBall anyway, we don't here.
  81.         }
  82.     return 0;
  83.     }
  84.  
  85. // OnDestroy:
  86. // Notify app main MDI frame window of destruction so it may
  87. // do some cleanup.  
  88. void CBounceWin::OnDestroy(void)
  89.     {
  90.     GetMDIFrame()->SendMessage(WM_CHILDDESTROY,(UINT)m_hWnd, 0);
  91.     }
  92.  
  93. // MakeNewBall:
  94. // Whenever a parameter changes which would affect the speed or appearance
  95. // of the ball, call this to regenerate the ball bitmap.
  96. //
  97. void CBounceWin::MakeNewBall(void)
  98.     {
  99.     if(m_pBitmap != NULL)
  100.         {
  101.         // Reclaim Windows resources associated with the ball bitmap
  102.         // before redrawing
  103.         m_pBitmap->DeleteObject();
  104.         }
  105.     else
  106.         m_pBitmap = new CBitmap;
  107.  
  108.     m_cxTotal = (m_cxRadius + ABS(m_cxMove)) << 1;
  109.     m_cyTotal = (m_cyRadius + ABS(m_cyMove)) << 1;
  110.  
  111.     CDC dcMem;
  112.     CDC* pDC = GetDC();
  113.     
  114.     dcMem.CreateCompatibleDC(pDC);
  115.  
  116.     m_pBitmap->CreateCompatibleBitmap(pDC, m_cxTotal, m_cyTotal);
  117.  
  118.     ASSERT(m_pBitmap->m_hObject != NULL);
  119.  
  120.     ReleaseDC(pDC);
  121.  
  122.     CBitmap* pOldBitmap = dcMem.SelectObject(m_pBitmap);
  123.  
  124.     // draw a rectangle in the background (window) color
  125.     CRect rect(0, 0, m_cxTotal, m_cyTotal);
  126.     CBrush brBackground(::GetSysColor(COLOR_WINDOW));
  127.     dcMem.FillRect(rect, &brBackground);
  128.  
  129.     CBrush brCross(HS_DIAGCROSS, 0L);
  130.     CBrush* pOldBrush = dcMem.SelectObject(&brCross);
  131.  
  132.     dcMem.SetBkColor(m_clrBall);
  133.     dcMem.Ellipse(ABS(m_cxMove), ABS(m_cyMove),
  134.                     m_cxTotal - ABS(m_cxMove), m_cyTotal - ABS(m_cyMove));
  135.  
  136.     dcMem.SelectObject(pOldBrush);
  137.     dcMem.SelectObject(pOldBitmap);
  138.     dcMem.DeleteDC();
  139.     }
  140.  
  141. // OnSize: ball size and displacement change according to the window size.
  142. void CBounceWin::OnSize(UINT nType, int cx, int cy)
  143.     {
  144.     m_xCenter = (m_cxClient = cx) >> 1;
  145.     m_yCenter = (m_cyClient = cy) >> 1;
  146.     m_xCenter += m_cxClient >> 3; // make the ball a little off-center
  147.  
  148.     LONG lScale = min((LONG)m_cxClient * m_xPixel,
  149.         (LONG)m_cyClient * m_yPixel) >> 4;
  150.     m_cxRadius = (short)(lScale / m_xPixel);
  151.     m_cyRadius = (short)(lScale / m_yPixel);
  152.     m_cxMove = max(1, m_cyRadius >> 2);
  153.     m_cyMove = max(1, m_cyRadius >> 2);
  154.  
  155.     MakeNewBall();
  156.  
  157.     CMDIChildWnd::OnSize(nType, cx, cy);
  158.     }
  159.  
  160. // OnColor: ball color needs to be changed.  Checkmark the right color on the
  161. // menu.
  162. void CBounceWin::OnColor(void)
  163.     {
  164.     CMenu* pMenu = GetMDIFrame()->GetMenu();
  165.     pMenu->CheckMenuItem(m_nColor, MF_UNCHECKED);
  166.  
  167.     m_nColor = GetCurrentMessage()->wParam;
  168.     pMenu->CheckMenuItem(m_nColor, MF_CHECKED);
  169.  
  170.     if(m_nColor != IDM_CUSTOM)
  171.         m_clrBall = clrTextArray[m_nColor - IDM_BLACK];
  172.     else
  173.         {
  174.         CColorDialog dlgColor(m_clrBall);
  175.         if(dlgColor.DoModal() == IDOK)
  176.             m_clrBall = dlgColor.GetColor();
  177.         }
  178.     MakeNewBall();
  179.     Invalidate();
  180.     }
  181.  
  182. // OnSpeed: ball speed needs to be changed.  Checkmark the menus, kill the
  183. // current timer and start a new one at the new speed.
  184. void CBounceWin::OnSpeed(void)
  185.     {
  186.     CMenu* pMenu = GetMDIFrame()->GetMenu();
  187.     pMenu->CheckMenuItem(m_nSpeed, MF_UNCHECKED);
  188.  
  189.     m_nSpeed = GetCurrentMessage()->wParam;
  190.     pMenu->CheckMenuItem(m_nSpeed, MF_CHECKED);
  191.  
  192.     KillTimer(1);
  193.     if(!SetTimer(1,(m_nSpeed==IDM_SLOW? 100 : 0), NULL))
  194.         {
  195.         MessageBox("Not enough timers available for this window.",
  196.                 "Viewer:Bounce", MB_ICONEXCLAMATION | MB_OK);
  197.  
  198.         m_nSpeed = 0;
  199.         DestroyWindow();
  200.         }
  201.     }
  202.  
  203. // OnTimer: Animate the ball.
  204. void CBounceWin::OnTimer(UINT)
  205.     {
  206.     if(m_pBitmap != NULL)
  207.         {
  208.         CDC* pdcScreen = GetDC();    
  209.  
  210.         CDC dcMem;
  211.         dcMem.CreateCompatibleDC(pdcScreen);
  212.  
  213.         ASSERT(m_pBitmap->m_hObject != NULL);
  214.  
  215.         CBitmap* pOldMap = dcMem.SelectObject(m_pBitmap);
  216.     
  217.         pdcScreen->BitBlt(m_xCenter - m_cxTotal / 2,
  218.                     m_yCenter - m_cyTotal / 2, m_cxTotal, m_cyTotal,
  219.                     &dcMem, 0, 0, SRCCOPY);
  220.     
  221.         ReleaseDC(pdcScreen);
  222.         m_xCenter += m_cxMove;
  223.         m_yCenter += m_cyMove;
  224.     
  225.         if((m_xCenter + m_cxRadius >= m_cxClient) || 
  226.                 (m_xCenter - m_cxRadius <= 0))
  227.             m_cxMove = -m_cxMove;
  228.         if((m_yCenter + m_cyRadius >= m_cyClient) || 
  229.                 (m_yCenter - m_cyRadius <= 0))
  230.             m_cyMove = -m_cyMove;
  231.         dcMem.SelectObject(pOldMap);
  232.         dcMem.DeleteDC();
  233.         }
  234.     }
  235.  
  236. // OnMDIActivate:
  237. // The current window is being activated or deactivated.  
  238. // Change MDI frame window menu as appropriate.
  239. //
  240.  
  241. void CBounceWin::OnMDIActivate(BOOL bActivate, CWnd*, CWnd*)
  242.     {
  243.     CMDIFrameWnd* pFrame = GetMDIFrame();
  244.     CMenu* pWinPopupMenu = NULL;
  245.     CMenu* pMenu = new CMenu;
  246.  
  247.     m_bWindowActive = bActivate;
  248.  
  249.     if(bActivate)
  250.         {
  251.         pMenu->LoadMenu("Bounce");
  252.         pWinPopupMenu = pMenu->GetSubMenu(BOUNCE_MENU_POS);
  253.         CMenu* pLastMenu = pFrame->MDISetMenu(pMenu, pWinPopupMenu);
  254.         pLastMenu->DestroyMenu();
  255.  
  256.         pMenu->CheckMenuItem(m_nColor, bActivate ? MF_CHECKED : MF_UNCHECKED);
  257.         pMenu->CheckMenuItem(m_nSpeed, bActivate ? MF_CHECKED : MF_UNCHECKED);
  258.         }
  259.     else
  260.         {
  261.         pMenu->LoadMenu("Init");
  262.         pWinPopupMenu = pMenu->GetSubMenu(INIT_MENU_POS);
  263.         CMenu* pLastMenu = pFrame->MDISetMenu(pMenu, pWinPopupMenu);
  264.         pLastMenu->DestroyMenu();
  265.         }
  266.     delete m_pMenuCurrent;
  267.     m_pMenuCurrent = pMenu;
  268.     pFrame->DrawMenuBar();
  269.     }
  270.  
  271.